package lab.cadl.lirui.markdown.core.parser

import lab.cadl.lirui.markdown.core.exceptions.MarkdownException
import lab.cadl.lirui.markdown.core.model.PaperRefDatabase
import lab.cadl.lirui.markdown.core.model.PaperRefEntry
import lab.cadl.lirui.markdown.core.model.PaperRefType
import org.jbibtex.BibTeXParser
import java.io.File
import java.io.InputStream

interface PaperRefLoader {
    fun accept(file: File): Boolean
    fun load(inputStream: InputStream, database: PaperRefDatabase)
}

object PaperRefLoaderRegistry {
    private val loaders: List<PaperRefLoader> = listOf(
            BibTexLoader()
    )

    fun findLoader(file: File): PaperRefLoader {
        return loaders.first { it.accept(file) }
    }
}

class BibTexLoader : PaperRefLoader {
    override fun accept(file: File): Boolean {
        return file.extension.toLowerCase() == "bib"
    }

    override fun load(inputStream: InputStream, database: PaperRefDatabase) {
        val parser = BibTeXParser()
        val db = parser.parse(inputStream.bufferedReader())
        for (bibEntry in db.entries) {
            val entry = PaperRefEntry(bibEntry.key.value, refType(bibEntry.value.type.value))
            for (field in bibEntry.value.fields) {
                entry.fields[field.key.value.toLowerCase()] = field.value.toUserString()
            }

            database.addEntry(entry)
        }
    }

    private fun refType(s: String): PaperRefType {
        return when (s.toLowerCase()) {
            "inproceedings" -> PaperRefType.CONFERENCE
            "conference" -> PaperRefType.CONFERENCE
            "incollection" -> PaperRefType.BOOK
            "book" -> PaperRefType.BOOK
            "booklet" -> PaperRefType.BOOK
            "inbook" -> PaperRefType.BOOK_SECTION
            "phdthesis" -> PaperRefType.THESIS
            "masterthesis" -> PaperRefType.THESIS
            "article" -> PaperRefType.JOURNAL
            else -> throw MarkdownException("unknown ref type $s")
        }
    }
}
